package com.fanghuaiming.seata.order.tcc.impl;

import com.fanghuaiming.seata.order.dao.mapper.SeataTccOrderMapper;
import com.fanghuaiming.seata.order.dao.model.SeataTccOrder;
import com.fanghuaiming.seata.order.tcc.SeataPhaseTccOrder;
import com.fanghuaiming.seata.order.tcc.idempotent.SeataTccOrderResultHolder;
import io.seata.rm.tcc.api.BusinessActionContext;
import java.math.BigDecimal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/****
 * @description: 订单tcc接口实现类
 * @version:1.0.0
 * @author fanghuaiming
 * @data Created in 2020/11/30 下午4:59
 *
 */
@Component
@Slf4j
public class SeataPhaseTccOrderImpl implements SeataPhaseTccOrder {

    /**
     * mapper
     */
    @Autowired
    private SeataTccOrderMapper seataTccOrderMapper;

    /**
     * @Description: 第一阶段
     *
     * @param:
     * @return:
     * @auther: fanghuaiming
     * @date: 2020/11/30 下午5:02
     * @version:1.0.0
     */
    @SuppressWarnings("all")
    @Transactional
    @Override
    public Boolean prepareCreateOrder(BusinessActionContext businessActionContext,
            Long orderId,
            Long userId,
            Long productId,
            Integer count,
            BigDecimal money) {
        //事务成功，保存一个标识，供第二阶段进行判断
        SeataTccOrderResultHolder.setResult(getClass(), businessActionContext.getXid(), "p");
        log.info("==========创建 订单 第一阶段，事务组Xid:{} ==========" , businessActionContext.getXid());
        SeataTccOrder order = new SeataTccOrder(orderId, userId, productId, count, money, 0);
        seataTccOrderMapper.create(order);
        return true;

    }

    /**
     * @Description: 第二阶段
     *
     * @param:
     * @return:
     * @auther: fanghuaiming
     * @date: 2020/11/30 下午5:03
     * @version:1.0.0
     */
    @SuppressWarnings("all")
    @Transactional
    @Override
    public boolean commit(BusinessActionContext businessActionContext) {
        log.info("==========即将开始Confirm-->创建 订单 第二阶段提交,事务组Xid:{} ==========",businessActionContext.getXid());

        // 防止幂等性，如果commit阶段重复执行则直接返回
        if (SeataTccOrderResultHolder.getResult(getClass(), businessActionContext.getXid()) == null) {
            log.info("订单Confirm已经确认过");
            return true;
        }

        //Long orderId = (Long) businessActionContext.getActionContext("orderId");
        long orderId = Long.parseLong(businessActionContext.getActionContext("orderId").toString());
        seataTccOrderMapper.updateStatus(orderId, 1);
        log.info("==========已经完成Confirm-->创建 订单 第二阶段提交,事务组Xid:{} ==========",businessActionContext.getXid());
        //提交成功时删除标识
        SeataTccOrderResultHolder.removeResult(getClass(), businessActionContext.getXid());
        return true;
    }

    /**
     * @Description: 第二阶段
     *
     * @param:
     * @return:
     * @auther: fanghuaiming
     * @date: 2020/11/30 下午5:03
     * @version:1.0.0
     */
    @SuppressWarnings("all")
    @Transactional
    @Override
    public boolean rollback(BusinessActionContext businessActionContext) {
        log.info("========== 即将开始Cancle-->创建 订单 第二阶段回滚,事务组Xid:{} =========="+businessActionContext.getXid());

        //第一阶段没有完成的情况下，不必执行回滚
        //因为第一阶段有本地事务，事务失败时已经进行了回滚。
        //如果这里第一阶段成功，而其他全局事务参与者失败，这里会执行回滚
        //幂等性控制：如果重复执行回滚则直接返回
        if (SeataTccOrderResultHolder.getResult(getClass(), businessActionContext.getXid()) == null) {
            log.info("订单Cancle已经取消过");
            return true;
        }

        //Long orderId = (Long) businessActionContext.getActionContext("orderId");
        long orderId = Long.parseLong(businessActionContext.getActionContext("orderId").toString());
        seataTccOrderMapper.deleteById(orderId);
        log.info("========== 已经完成Cancle-->创建 订单 第二阶段回滚,事务组Xid:{} =========="+businessActionContext.getXid());
        //回滚结束时，删除标识
        SeataTccOrderResultHolder.removeResult(getClass(), businessActionContext.getXid());
        return true;
    }
}
